package cn.eva.service.Impl.job;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.eva.common.LayuiTableResult;
import cn.eva.common.MiniConstant;
import cn.eva.common.ResultJosn;
import cn.eva.common.enums.JobStatus;
import cn.eva.entity.AddJobInfo;
import cn.eva.entity.SysJobBaseInfo;
import cn.eva.job.BaseJob;
import cn.eva.job.impl.StatisticalFractionJob;
import cn.eva.service.job.JobService;
import cn.eva.service.job.SysJobBaseInfoService;
import cn.eva.utils.CronUtils;

@Service
public class JobServiceImpl implements JobService {

	@Autowired
	private SysJobBaseInfoService jobBaseInfoService;

	//加入Qulifier注解，通过名称注入bean
	@Autowired
	private Scheduler scheduler;

	private static Logger log = LoggerFactory.getLogger(JobService.class);

	@Override
	public ResultJosn saveJob(SysJobBaseInfo jobBaseInfo) throws Exception {
		// 启动调度器  
		scheduler.start();

		String jobClassName = jobBaseInfo.getJobClassName();
		String jobGroupName = jobBaseInfo.getJobGroupName();
		String cronExpression = jobBaseInfo.getCron();
		//构建job信息
		JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
				.withIdentity(jobClassName, jobGroupName).build();
		jobDetail.getJobDataMap().put(MiniConstant.JOB_DATA_KEY, jobBaseInfo);
		//表达式调度构建器(即任务执行的时间)
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

		//按新的cronExpression表达式构建一个新的trigger
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
				.withSchedule(scheduleBuilder).build();

		try {
			scheduler.scheduleJob(jobDetail, trigger);
			//添加job基本信息
			jobBaseInfoService.addJob(jobBaseInfo);
		} catch (SchedulerException e) {
			log.error("创建定时任务失败" + e);
			throw new Exception("创建定时任务失败");
		}
		return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
	}

	/**
	 * 
	 * <p>Title: pause</p>   
	 * <p>Description: 暂停任务</p>   
	 * @param jobBaseInfo
	 * @return
	 * @throws Exception   
	 * @see cn.eva.service.job.JobService#pause(cn.eva.entity.SysJobBaseInfo)
	 */
	@Override
	public ResultJosn pause(SysJobBaseInfo jobBaseInfo) throws Exception {
		scheduler.pauseJob(JobKey.jobKey(jobBaseInfo.getJobClassName(), jobBaseInfo.getJobGroupName()));
		//更新job基本信息
		jobBaseInfo.setStatus(JobStatus.PAUSE.getCode());
		jobBaseInfoService.updJob(jobBaseInfo);
		return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
	}

	/**
	 * 
	 * <p>Title: resumejob</p>   
	 * <p>Description: 恢复任务，如果不存在，就创建</p>   
	 * @param jobBaseInfo
	 * @return
	 * @throws Exception   
	 * @see cn.eva.service.job.JobService#resumejob(cn.eva.entity.SysJobBaseInfo)
	 */
	@Override
	public ResultJosn resumejob(SysJobBaseInfo jobBaseInfo) throws Exception {
		TriggerKey triggerKey = TriggerKey.triggerKey(jobBaseInfo.getJobClassName(), jobBaseInfo.getJobGroupName());
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		if (null == trigger) {
			return this.saveJob(jobBaseInfo);
		} else {
			JobKey jobKey = JobKey.jobKey(jobBaseInfo.getJobClassName(), jobBaseInfo.getJobGroupName());
			scheduler.resumeJob(jobKey);
			//更新job基本信息
			jobBaseInfo.setStatus(JobStatus.RUN.getCode());
			jobBaseInfoService.updJob(jobBaseInfo);
			return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
		}
	}

	@Override
	public ResultJosn reschedulejob(SysJobBaseInfo jobBaseInfo) throws Exception {

		String jobClassName = jobBaseInfo.getJobClassName();
		String jobGroupName = jobBaseInfo.getJobGroupName();
		String cronExpression = jobBaseInfo.getCron();
		try {
			TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
			// 表达式调度构建器
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

			if (null != trigger) {
				// 按新的cronExpression表达式重新构建trigger
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

				// 按新的trigger重新设置job执行
				scheduler.rescheduleJob(triggerKey, trigger);
				//更新job基本信息
				jobBaseInfoService.updJob(jobBaseInfo);
			}
			return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
		} catch (SchedulerException e) {
			System.out.println("更新定时任务失败" + e);
			throw new Exception("更新定时任务失败");
		}

	}

	@Override
	public ResultJosn deletejob(SysJobBaseInfo jobBaseInfo) throws Exception {
		String jobClassName = jobBaseInfo.getJobClassName();
		String jobGroupName = jobBaseInfo.getJobGroupName();
		scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
		scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
		scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
		jobBaseInfoService.delJob(jobBaseInfo);
		return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");

	}

	public static BaseJob getClass(String classname) throws Exception {
		Class<?> class1 = Class.forName(classname);
		return (BaseJob) class1.newInstance();
	}

	@Override
	public LayuiTableResult getJobAndTriggerDetails(SysJobBaseInfo jobBaseInfo, Integer page, Integer pageSize) {
		return jobBaseInfoService.seletByPage(jobBaseInfo, page, pageSize);
	}

	@Override
	public SysJobBaseInfo getJobInfoById(Long id) {
		return jobBaseInfoService.selectById(id);
	}

	/**
	 * 
	 * <p>Title: addUp</p>   
	 * <p>Description: 添加统计日期任务 </p>   
	 * @param addJobInfo
	 * @return   
	 * @throws Exception 
	 * @see cn.eva.service.job.JobService#addUp(cn.eva.entity.AddJobInfo)
	 */
	@Override
	@Transactional
	public ResultJosn addUp(AddJobInfo addJobInfo) throws Exception {
		//添加定时任务
		SysJobBaseInfo jobBaseInfo = new SysJobBaseInfo();
		jobBaseInfo.setJobName(addJobInfo.getJobName());
		jobBaseInfo.setJobDesc(addJobInfo.getJobName());
		jobBaseInfo.setJobClassName(StatisticalFractionJob.class.getName());
		jobBaseInfo.setJobGroupName(addJobInfo.getJobGroupName());
		jobBaseInfo.setCron(CronUtils.getCron(addJobInfo.getDeadline()));
		this.saveJob(jobBaseInfo);
		return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
	}

	/**
	 * 
	 * <p>Title: updUp</p>   
	 * <p>Description: 更新任务</p>   
	 * @param addJobInfo
	 * @return
	 * @throws Exception   
	 * @see cn.eva.service.job.JobService#updUp(cn.eva.entity.AddJobInfo)
	 */
	@Override
	public ResultJosn updUp(AddJobInfo addJobInfo) throws Exception {
		//更新定时任务
		SysJobBaseInfo jobBaseInfo = new SysJobBaseInfo();
		jobBaseInfo.setJobName(addJobInfo.getJobName());
		jobBaseInfo.setJobDesc(addJobInfo.getJobName());
		jobBaseInfo.setJobClassName(StatisticalFractionJob.class.getName());
		jobBaseInfo.setJobGroupName(addJobInfo.getJobGroupName());
		jobBaseInfo.setCron(CronUtils.getCron(addJobInfo.getDeadline()));
		this.reschedulejob(jobBaseInfo);
		return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
	}

	/**
	 * 
	 * <p>Title: delUp</p>   
	 * <p>Description: 删除统计日期分数 </p>   
	 * @param addJobInfo
	 * @return   
	 * @throws Exception 
	 * @see cn.eva.service.job.JobService#delUp(cn.eva.entity.AddJobInfo)
	 */
	@Override
	public ResultJosn delUp(AddJobInfo addJobInfo) throws Exception {
		SysJobBaseInfo jobBaseInfo = new SysJobBaseInfo();
		jobBaseInfo.setJobClassName(StatisticalFractionJob.class.getName());
		jobBaseInfo.setJobGroupName(addJobInfo.getJobGroupName());
		this.deletejob(jobBaseInfo);
		return new ResultJosn(HttpStatus.OK.value(), "操作成功", "操作成功");
	}

	@Override
	public ResultJosn pause(AddJobInfo addJobInfo) throws Exception {
		SysJobBaseInfo jobBaseInfo = new SysJobBaseInfo();
		jobBaseInfo.setJobClassName(StatisticalFractionJob.class.getName());
		jobBaseInfo.setJobGroupName(addJobInfo.getJobGroupName());
		this.pause(jobBaseInfo);
		return null;
	}

	@Override
	public ResultJosn resumejob(AddJobInfo addJobInfo) throws Exception {
		SysJobBaseInfo jobBaseInfo = new SysJobBaseInfo();
		jobBaseInfo.setJobClassName(StatisticalFractionJob.class.getName());
		jobBaseInfo.setJobGroupName(addJobInfo.getJobGroupName());
		jobBaseInfo.setCron(CronUtils.getCron(addJobInfo.getDeadline()));
		this.resumejob(jobBaseInfo);
		return null;
	}
}
